#include "stdafx.h"
#include "InstanceQuad3.h"
#include "Camera2D.h"
#include <vector>

const int MaxParticles = 2;
static GLfloat g_particule_position_size_data3[MaxParticles * 3];
static GLubyte g_particule_color_data3[MaxParticles * 4];

namespace a2d
{
//------------------------------------------------------------------
	
	static const GLfloat g_vertex_buffer_data[] =
	{
		-0.5f, -0.5f,
		0.5f, -0.5f,
		-0.5f, 0.5f,
		0.5f, 0.5f,
	};
			
	VAO InstanceQuad3::m_vao;
	ShaderProgram InstanceQuad3::m_shaders;

	bool InstanceQuad3::Create()
	{
		if ( !m_vao.Create() )
			return false;
		m_vao.Bind();

		if ( !m_shaders.Load("../Particle.vert", "../Particle.frag") )
			return false;

		// Vertex shader
		CameraRight_worldspace_ID3 = glGetUniformLocation(m_shaders.GetProgramID(), "CameraRight_worldspace");
		CameraUp_worldspace_ID3 = glGetUniformLocation(m_shaders.GetProgramID(), "CameraUp_worldspace");
		ViewProjMatrixID3 = glGetUniformLocation(m_shaders.GetProgramID(), "VP");
		// fragment shader
		TextureID3 = glGetUniformLocation(m_shaders.GetProgramID(), "myTextureSampler");

		if ( !m_tex.Create("../Test/dragon.png") )
			return false;
		
		glGenBuffers(1, &billboard_vertex_buffer3);
		glBindBuffer(GL_ARRAY_BUFFER, billboard_vertex_buffer3);
		glBufferData(GL_ARRAY_BUFFER, sizeof(g_vertex_buffer_data), g_vertex_buffer_data, GL_STATIC_DRAW);

		glGenBuffers(1, &particles_position_buffer3);
		glBindBuffer(GL_ARRAY_BUFFER, particles_position_buffer3);
		glBufferData(GL_ARRAY_BUFFER, MaxParticles * 3 * sizeof(GLfloat), NULL, GL_STREAM_DRAW);

		glGenBuffers(1, &particles_color_buffer3);
		glBindBuffer(GL_ARRAY_BUFFER, particles_color_buffer3);
		glBufferData(GL_ARRAY_BUFFER, MaxParticles * 4 * sizeof(GLubyte), NULL, GL_STREAM_DRAW);

		ProjectionMatrix3 = Camera2D::Get().GetOrthoMatrix();

		for ( int i = 0; i < MaxParticles; i++ )
		{
			g_particule_position_size_data3[3 * i + 0] = i*0.5f;
			g_particule_position_size_data3[3 * i + 1] = 0.0f;
			g_particule_position_size_data3[3 * i + 2] = -i*0.5f;

			g_particule_color_data3[4 * i + 0] = 255;
			g_particule_color_data3[4 * i + 1] = 255;
			g_particule_color_data3[4 * i + 2] = 255;
			g_particule_color_data3[4 * i + 3] = 255;
		}
		return true;
	}

	void InstanceQuad3::Draw()
	{
		m_tex.Bind();
		m_vao.Bind();
		//m_vbo.Bind();
		m_shaders.Bind();

		//computeMatricesFromInputs3();		
		//glm::vec3 CameraPosition(glm::inverse(ViewMatrix3)[3]);		
		glm::mat4 ViewProjectionMatrix = ProjectionMatrix3 /** ViewMatrix3*/;
		
		glBindBuffer(GL_ARRAY_BUFFER, particles_position_buffer3);
		glBufferData(GL_ARRAY_BUFFER, MaxParticles*3*sizeof(GLfloat), NULL, GL_STREAM_DRAW);
		glBufferSubData(GL_ARRAY_BUFFER, 0, MaxParticles*3*sizeof(GLfloat), g_particule_position_size_data3);
		
		glBindBuffer(GL_ARRAY_BUFFER, particles_color_buffer3);
		glBufferData(GL_ARRAY_BUFFER, MaxParticles*4*sizeof(GLubyte), NULL, GL_STREAM_DRAW);
		glBufferSubData(GL_ARRAY_BUFFER, 0, MaxParticles*4*sizeof(GLubyte), g_particule_color_data3);

		glUniform1i(TextureID3, 0);
		
		glUniform3f(CameraRight_worldspace_ID3, ViewMatrix3[0][0], ViewMatrix3[1][0], ViewMatrix3[2][0]);
		glUniform3f(CameraUp_worldspace_ID3, ViewMatrix3[0][1], ViewMatrix3[1][1], ViewMatrix3[2][1]);		
		glUniformMatrix4fv(ViewProjMatrixID3, 1, GL_FALSE, &ViewProjectionMatrix[0][0]);
		
		glEnableVertexAttribArray(0);
		glBindBuffer(GL_ARRAY_BUFFER, billboard_vertex_buffer3);
		glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, (void*)0);

		glEnableVertexAttribArray(1);
		glBindBuffer(GL_ARRAY_BUFFER, particles_position_buffer3);
		glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, (void*)0);
		
		glEnableVertexAttribArray(2);
		glBindBuffer(GL_ARRAY_BUFFER, particles_color_buffer3);
		glVertexAttribPointer(2, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, (void*)0);
				
		glVertexAttribDivisor(0, 0); 
		glVertexAttribDivisor(1, 1);
		glVertexAttribDivisor(2, 1);
		
		glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, MaxParticles);
		
		glDisableVertexAttribArray(0);
		glDisableVertexAttribArray(1);
		glDisableVertexAttribArray(2);
	}

	void InstanceQuad3::Destroy()
	{
		m_tex.Destroy();
		//m_vbo.Destroy();
		m_shaders.Destroy();
		m_vao.Destroy();
	}

	void InstanceQuad3::computeMatricesFromInputs3()
	{
		//// Initial position : on +Z
		//const glm::vec3 position3 = glm::vec3(0, 0, 2);
		//// Initial horizontal angle : toward -Z
		//const float horizontalAngle3 = 3.14f;
		//// Initial vertical angle : none
		//const float verticalAngle3 = 0.0f;
		//const float speed3 = 10.0f; // 3 units / second
		//const float mouseSpeed3 = 0.005f;

		//// Direction : Spherical coordinates to Cartesian coordinates conversion
		//glm::vec3 direction(
		//	cos(verticalAngle3) * sin(horizontalAngle3),
		//	sin(verticalAngle3),
		//	cos(verticalAngle3) * cos(horizontalAngle3)
		//	);

		//// Right vector
		//glm::vec3 right = glm::vec3(
		//	sin(horizontalAngle3 - 3.14f / 2.0f),
		//	0,
		//	cos(horizontalAngle3 - 3.14f / 2.0f)
		//	);

		//// Up vector
		//glm::vec3 up = glm::cross(right, direction);

		//ProjectionMatrix3 = glm::perspective(45.0f, 4.0f / 3.0f, 0.1f, 100.0f);
		//ViewMatrix3 = glm::lookAt(position3, position3 + direction, up);
	}

//------------------------------------------------------------------
} // namespace a2d
